home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Heretic Source / P_SPEC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-13  |  28.3 KB  |  1,254 lines

  1.  
  2. // P_Spec.c
  3.  
  4. #include "DoomDef.h"
  5. #include "P_local.h"
  6. #include "soundst.h"
  7.  
  8. // Macros
  9.  
  10. #define MAX_AMBIENT_SFX 8 // Per level
  11.  
  12. // Types
  13.  
  14. typedef enum
  15. {
  16.     afxcmd_play,        // (sound)
  17.     afxcmd_playabsvol,    // (sound, volume)
  18.     afxcmd_playrelvol,    // (sound, volume)
  19.     afxcmd_delay,        // (ticks)
  20.     afxcmd_delayrand,    // (andbits)
  21.     afxcmd_end            // ()
  22. } afxcmd_t;
  23.  
  24. // Data
  25.  
  26. int *LevelAmbientSfx[MAX_AMBIENT_SFX];
  27. int *AmbSfxPtr;
  28. int AmbSfxCount;
  29. int AmbSfxTics;
  30. int AmbSfxVolume;
  31.  
  32. int AmbSndSeqInit[] =
  33. { // Startup
  34.     afxcmd_end
  35. };
  36. int AmbSndSeq1[] =
  37. { // Scream
  38.     afxcmd_play, sfx_amb1,
  39.     afxcmd_end
  40. };
  41. int AmbSndSeq2[] =
  42. { // Squish
  43.     afxcmd_play, sfx_amb2,
  44.     afxcmd_end
  45. };
  46. int AmbSndSeq3[] =
  47. { // Drops
  48.     afxcmd_play, sfx_amb3,
  49.     afxcmd_delay, 16,
  50.     afxcmd_delayrand, 31,
  51.     afxcmd_play, sfx_amb7,
  52.     afxcmd_delay, 16,
  53.     afxcmd_delayrand, 31,
  54.     afxcmd_play, sfx_amb3,
  55.     afxcmd_delay, 16,
  56.     afxcmd_delayrand, 31,
  57.     afxcmd_play, sfx_amb7,
  58.     afxcmd_delay, 16,
  59.     afxcmd_delayrand, 31,
  60.     afxcmd_play, sfx_amb3,
  61.     afxcmd_delay, 16,
  62.     afxcmd_delayrand, 31,
  63.     afxcmd_play, sfx_amb7,
  64.     afxcmd_delay, 16,
  65.     afxcmd_delayrand, 31,
  66.     afxcmd_end
  67. };
  68. int AmbSndSeq4[] =
  69. { // SlowFootSteps
  70.     afxcmd_play, sfx_amb4,
  71.     afxcmd_delay, 15,
  72.     afxcmd_playrelvol, sfx_amb11, -3,
  73.     afxcmd_delay, 15,
  74.     afxcmd_playrelvol, sfx_amb4, -3,
  75.     afxcmd_delay, 15,
  76.     afxcmd_playrelvol, sfx_amb11, -3,
  77.     afxcmd_delay, 15,
  78.     afxcmd_playrelvol, sfx_amb4, -3,
  79.     afxcmd_delay, 15,
  80.     afxcmd_playrelvol, sfx_amb11, -3,
  81.     afxcmd_delay, 15,
  82.     afxcmd_playrelvol, sfx_amb4, -3,
  83.     afxcmd_delay, 15,
  84.     afxcmd_playrelvol, sfx_amb11, -3,
  85.     afxcmd_end
  86. };
  87. int AmbSndSeq5[] =
  88. { // Heartbeat
  89.     afxcmd_play, sfx_amb5,
  90.     afxcmd_delay, 35,
  91.     afxcmd_play, sfx_amb5,
  92.     afxcmd_delay, 35,
  93.     afxcmd_play, sfx_amb5,
  94.     afxcmd_delay, 35,
  95.     afxcmd_play, sfx_amb5,
  96.     afxcmd_end
  97. };
  98. int AmbSndSeq6[] =
  99. { // Bells
  100.     afxcmd_play, sfx_amb6,
  101.     afxcmd_delay, 17,
  102.     afxcmd_playrelvol, sfx_amb6, -8,
  103.     afxcmd_delay, 17,
  104.     afxcmd_playrelvol, sfx_amb6, -8,
  105.     afxcmd_delay, 17,
  106.     afxcmd_playrelvol, sfx_amb6, -8,
  107.     afxcmd_end
  108. };
  109. int AmbSndSeq7[] =
  110. { // Growl
  111.     afxcmd_play, sfx_bstsit,
  112.     afxcmd_end
  113. };
  114. int AmbSndSeq8[] =
  115. { // Magic
  116.     afxcmd_play, sfx_amb8,
  117.     afxcmd_end
  118. };
  119. int AmbSndSeq9[] =
  120. { // Laughter
  121.     afxcmd_play, sfx_amb9,
  122.     afxcmd_delay, 16,
  123.     afxcmd_playrelvol, sfx_amb9, -4,
  124.     afxcmd_delay, 16,
  125.     afxcmd_playrelvol, sfx_amb9, -4,
  126.     afxcmd_delay, 16,
  127.     afxcmd_playrelvol, sfx_amb10, -4,
  128.     afxcmd_delay, 16,
  129.     afxcmd_playrelvol, sfx_amb10, -4,
  130.     afxcmd_delay, 16,
  131.     afxcmd_playrelvol, sfx_amb10, -4,
  132.     afxcmd_end
  133. };
  134. int AmbSndSeq10[] =
  135. { // FastFootsteps
  136.     afxcmd_play, sfx_amb4,
  137.     afxcmd_delay, 8,
  138.     afxcmd_playrelvol, sfx_amb11, -3,
  139.     afxcmd_delay, 8,
  140.     afxcmd_playrelvol, sfx_amb4, -3,
  141.     afxcmd_delay, 8,
  142.     afxcmd_playrelvol, sfx_amb11, -3,
  143.     afxcmd_delay, 8,
  144.     afxcmd_playrelvol, sfx_amb4, -3,
  145.     afxcmd_delay, 8,
  146.     afxcmd_playrelvol, sfx_amb11, -3,
  147.     afxcmd_delay, 8,
  148.     afxcmd_playrelvol, sfx_amb4, -3,
  149.     afxcmd_delay, 8,
  150.     afxcmd_playrelvol, sfx_amb11, -3,
  151.     afxcmd_end
  152. };
  153.  
  154. int *AmbientSfx[] =
  155. {
  156.     AmbSndSeq1,        // Scream
  157.     AmbSndSeq2,        // Squish
  158.     AmbSndSeq3,        // Drops
  159.     AmbSndSeq4,        // SlowFootsteps
  160.     AmbSndSeq5,        // Heartbeat
  161.     AmbSndSeq6,        // Bells
  162.     AmbSndSeq7,        // Growl
  163.     AmbSndSeq8,        // Magic
  164.     AmbSndSeq9,        // Laughter
  165.     AmbSndSeq10        // FastFootsteps
  166. };
  167.  
  168. animdef_t animdefs[] =
  169. {
  170.     // false = flat
  171.     // true = texture
  172.     {false, "FLTWAWA3", "FLTWAWA1", 8}, // Water
  173.     {false, "FLTSLUD3", "FLTSLUD1", 8}, // Sludge
  174.     {false, "FLTTELE4", "FLTTELE1", 6}, // Teleport
  175.     {false, "FLTFLWW3", "FLTFLWW1", 9}, // River - West
  176.     {false, "FLTLAVA4", "FLTLAVA1", 8}, // Lava
  177.     {false, "FLATHUH4", "FLATHUH1", 8}, // Super Lava
  178.     {true, "LAVAFL3", "LAVAFL1", 6}, // Texture: Lavaflow
  179.     {true, "WATRWAL3", "WATRWAL1", 4}, // Texture: Waterfall
  180.     {-1}
  181. };
  182.  
  183. anim_t anims[MAXANIMS];
  184. anim_t *lastanim;
  185.  
  186. int *TerrainTypes;
  187. struct
  188. {
  189.     char *name;
  190.     int type;
  191. } TerrainTypeDefs[] =
  192. {
  193.     { "FLTWAWA1", FLOOR_WATER },
  194.     { "FLTFLWW1", FLOOR_WATER },
  195.     { "FLTLAVA1", FLOOR_LAVA },
  196.     { "FLATHUH1", FLOOR_LAVA },
  197.     { "FLTSLUD1", FLOOR_SLUDGE },
  198.     { "END", -1 }
  199. };
  200.  
  201. mobj_t LavaInflictor;
  202.  
  203. //----------------------------------------------------------------------------
  204. //
  205. // PROC P_InitLava
  206. //
  207. //----------------------------------------------------------------------------
  208.  
  209. void P_InitLava(void)
  210. {
  211.     memset(&LavaInflictor, 0, sizeof(mobj_t));
  212.     LavaInflictor.type = MT_PHOENIXFX2;
  213.     LavaInflictor.flags2 = MF2_FIREDAMAGE|MF2_NODMGTHRUST;
  214. }
  215.  
  216. //----------------------------------------------------------------------------
  217. //
  218. // PROC P_InitTerrainTypes
  219. //
  220. //----------------------------------------------------------------------------
  221.  
  222. void P_InitTerrainTypes(void)
  223. {
  224.     int i;
  225.     int lump;
  226.     int size;
  227.  
  228.     size = (numflats+1)*sizeof(int);
  229.     TerrainTypes = Z_Malloc(size, PU_STATIC, 0);
  230.     memset(TerrainTypes, 0, size);
  231.     for(i = 0; TerrainTypeDefs[i].type != -1; i++)
  232.     {
  233.         lump = W_CheckNumForName(TerrainTypeDefs[i].name);
  234.         if(lump != -1)
  235.         {
  236.             TerrainTypes[lump-firstflat] = TerrainTypeDefs[i].type;
  237.         }
  238.     }
  239. }
  240.  
  241. //----------------------------------------------------------------------------
  242. //
  243. // PROC P_InitPicAnims
  244. //
  245. //----------------------------------------------------------------------------
  246.  
  247. void P_InitPicAnims(void)
  248. {
  249.     int i;
  250.  
  251.     lastanim = anims;
  252.     for(i = 0; animdefs[i].istexture != -1; i++)
  253.     {
  254.         if(animdefs[i].istexture)
  255.         { // Texture animation
  256.             if(R_CheckTextureNumForName(animdefs[i].startname) == -1)
  257.             { // Texture doesn't exist
  258.                 continue;
  259.             }
  260.             lastanim->picnum = R_TextureNumForName(animdefs[i].endname);
  261.             lastanim->basepic = R_TextureNumForName(animdefs[i].startname);
  262.         }
  263.         else
  264.         { // Flat animation
  265.             if(W_CheckNumForName(animdefs[i].startname) == -1)
  266.             { // Flat doesn't exist
  267.                 continue;
  268.             }
  269.             lastanim->picnum = R_FlatNumForName(animdefs[i].endname);
  270.             lastanim->basepic = R_FlatNumForName(animdefs[i].startname);
  271.         }
  272.         lastanim->istexture = animdefs[i].istexture;
  273.         lastanim->numpics = lastanim->picnum-lastanim->basepic+1;
  274.         if(lastanim->numpics < 2)
  275.         {
  276.             I_Error("P_InitPicAnims: bad cycle from %s to %s",
  277.                 animdefs[i].startname, animdefs[i].endname);
  278.         }
  279.         lastanim->speed = animdefs[i].speed;
  280.         lastanim++;
  281.     }
  282. }
  283.  
  284. /*
  285. ==============================================================================
  286.  
  287.                             UTILITIES
  288.  
  289. ==============================================================================
  290. */
  291.  
  292. //
  293. //    Will return a side_t* given the number of the current sector,
  294. //        the line number, and the side (0/1) that you want.
  295. //
  296. side_t *getSide(int currentSector,int line, int side)
  297. {
  298.     return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
  299. }
  300.  
  301. //
  302. //    Will return a sector_t* given the number of the current sector,
  303. //        the line number and the side (0/1) that you want.
  304. //
  305. sector_t *getSector(int currentSector,int line,int side)
  306. {
  307.     return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
  308. }
  309.  
  310. //
  311. //    Given the sector number and the line number, will tell you whether
  312. //        the line is two-sided or not.
  313. //
  314. int    twoSided(int sector,int line)
  315. {
  316.     return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
  317. }
  318.  
  319. //==================================================================
  320. //
  321. //    Return sector_t * of sector next to current. NULL if not two-sided line
  322. //
  323. //==================================================================
  324. sector_t *getNextSector(line_t *line,sector_t *sec)
  325. {
  326.     if (!(line->flags & ML_TWOSIDED))
  327.         return NULL;
  328.         
  329.     if (line->frontsector == sec)
  330.         return line->backsector;
  331.     
  332.     return line->frontsector;
  333. }
  334.  
  335. //==================================================================
  336. //
  337. //    FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
  338. //
  339. //==================================================================
  340. fixed_t    P_FindLowestFloorSurrounding(sector_t *sec)
  341. {
  342.     int            i;
  343.     line_t        *check;
  344.     sector_t    *other;
  345.     fixed_t        floor = sec->floorheight;
  346.     
  347.     for (i=0 ;i < sec->linecount ; i++)
  348.     {
  349.         check = sec->lines[i];
  350.         other = getNextSector(check,sec);
  351.         if (!other)
  352.             continue;
  353.         if (other->floorheight < floor)
  354.             floor = other->floorheight;
  355.     }
  356.     return floor;
  357. }
  358.  
  359. //==================================================================
  360. //
  361. //    FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
  362. //
  363. //==================================================================
  364. fixed_t    P_FindHighestFloorSurrounding(sector_t *sec)
  365. {
  366.     int            i;
  367.     line_t        *check;
  368.     sector_t    *other;
  369.     fixed_t        floor = -500*FRACUNIT;
  370.     
  371.     for (i=0 ;i < sec->linecount ; i++)
  372.     {
  373.         check = sec->lines[i];
  374.         other = getNextSector(check,sec);
  375.         if (!other)
  376.             continue;            
  377.         if (other->floorheight > floor)
  378.             floor = other->floorheight;
  379.     }
  380.     return floor;
  381. }
  382.  
  383. //==================================================================
  384. //
  385. //    FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
  386. //
  387. //==================================================================
  388. fixed_t    P_FindNextHighestFloor(sector_t *sec,int currentheight)
  389. {
  390.     int            i;
  391.     int            h;
  392.     int            min;
  393.     line_t        *check;
  394.     sector_t    *other;
  395.     fixed_t        height = currentheight;
  396.     fixed_t        heightlist[20];        // 20 adjoining sectors max!
  397.     
  398.     for (i =0,h = 0 ;i < sec->linecount ; i++)
  399.     {
  400.         check = sec->lines[i];
  401.         other = getNextSector(check,sec);
  402.         if (!other)
  403.             continue;
  404.         if (other->floorheight > height)
  405.             heightlist[h++] = other->floorheight;
  406.     }
  407.     
  408.     //
  409.     // Find lowest height in list
  410.     //
  411.     min = heightlist[0];
  412.     for (i = 1;i < h;i++)
  413.         if (heightlist[i] < min)
  414.             min = heightlist[i];
  415.             
  416.     return min;
  417. }
  418.  
  419. //==================================================================
  420. //
  421. //    FIND LOWEST CEILING IN THE SURROUNDING SECTORS
  422. //
  423. //==================================================================
  424. fixed_t    P_FindLowestCeilingSurrounding(sector_t *sec)
  425. {
  426.     int            i;
  427.     line_t        *check;
  428.     sector_t    *other;
  429.     fixed_t        height = MAXINT;
  430.     
  431.     for (i=0 ;i < sec->linecount ; i++)
  432.     {
  433.         check = sec->lines[i];
  434.         other = getNextSector(check,sec);
  435.         if (!other)
  436.             continue;
  437.         if (other->ceilingheight < height)
  438.             height = other->ceilingheight;
  439.     }
  440.     return height;
  441. }
  442.  
  443. //==================================================================
  444. //
  445. //    FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
  446. //
  447. //==================================================================
  448. fixed_t    P_FindHighestCeilingSurrounding(sector_t *sec)
  449. {
  450.     int    i;
  451.     line_t    *check;
  452.     sector_t    *other;
  453.     fixed_t    height = 0;
  454.     
  455.     for (i=0 ;i < sec->linecount ; i++)
  456.     {
  457.         check = sec->lines[i];
  458.         other = getNextSector(check,sec);
  459.         if (!other)
  460.             continue;
  461.         if (other->ceilingheight > height)
  462.             height = other->ceilingheight;
  463.     }
  464.     return height;
  465. }
  466.  
  467. //==================================================================
  468. //
  469. //    RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
  470. //
  471. //==================================================================
  472. int    P_FindSectorFromLineTag(line_t    *line,int start)
  473. {
  474.     int    i;
  475.     
  476.     for (i=start+1;i<numsectors;i++)
  477.         if (sectors[i].tag == line->tag)
  478.             return i;
  479.     return -1;
  480. }
  481.  
  482. //==================================================================
  483. //
  484. //    Find minimum light from an adjacent sector
  485. //
  486. //==================================================================
  487. int    P_FindMinSurroundingLight(sector_t *sector,int max)
  488. {
  489.     int            i;
  490.     int            min;
  491.     line_t        *line;
  492.     sector_t    *check;
  493.     
  494.     min = max;
  495.     for (i=0 ; i < sector->linecount ; i++)
  496.     {
  497.         line = sector->lines[i];
  498.         check = getNextSector(line,sector);
  499.         if (!check)
  500.             continue;
  501.         if (check->lightlevel < min)
  502.             min = check->lightlevel;
  503.     }
  504.     return min;
  505. }
  506.  
  507. /*
  508. ==============================================================================
  509.  
  510.                             EVENTS
  511.  
  512. Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers
  513.  
  514. ==============================================================================
  515. */
  516.  
  517.  
  518.  
  519. /*
  520. ===============================================================================
  521. =
  522. = P_CrossSpecialLine - TRIGGER
  523. =
  524. = Called every time a thing origin is about to cross
  525. = a line with a non 0 special
  526. =
  527. ===============================================================================
  528. */
  529.  
  530. void P_CrossSpecialLine(int linenum, int side, mobj_t *thing)
  531. {
  532.     line_t *line;
  533.  
  534.     line = &lines[linenum];
  535.     if(!thing->player)
  536.     { // Check if trigger allowed by non-player mobj
  537.         switch(line->special)
  538.         {
  539.             case 39:    // Trigger_TELEPORT
  540.             case 97:    // Retrigger_TELEPORT
  541.             case 4:        // Trigger_Raise_Door
  542.             //case 10:    // PLAT DOWN-WAIT-UP-STAY TRIGGER
  543.             //case 88:    // PLAT DOWN-WAIT-UP-STAY RETRIGGER
  544.                 break;
  545.             default:
  546.                 return;
  547.                 break;
  548.         }
  549.     }
  550.     switch(line->special)
  551.     {
  552.         //====================================================
  553.         // TRIGGERS
  554.         //====================================================
  555.         case 2: // Open Door
  556.             EV_DoDoor(line,open,VDOORSPEED);
  557.             line->special = 0;
  558.             break;
  559.         case 3: // Close Door
  560.             EV_DoDoor(line,close,VDOORSPEED);
  561.             line->special = 0;
  562.             break;
  563.         case 4: // Raise Door
  564.             EV_DoDoor(line,normal,VDOORSPEED);
  565.             line->special = 0;
  566.             break;
  567.         case 5: // Raise Floor
  568.             EV_DoFloor(line,raiseFloor);
  569.             line->special = 0;
  570.             break;
  571.         case 6: // Fast Ceiling Crush & Raise
  572.             EV_DoCeiling(line,fastCrushAndRaise);
  573.             line->special = 0;
  574.             break;
  575.         case 8: // Trigger_Build_Stairs (8 pixel steps)
  576.             EV_BuildStairs(line, 8*FRACUNIT);
  577.             line->special = 0;
  578.             break;
  579.         case 106: // Trigger_Build_Stairs_16 (16 pixel steps)
  580.             EV_BuildStairs(line, 16*FRACUNIT);
  581.             line->special = 0;
  582.             break;
  583.         case 10: // PlatDownWaitUp
  584.             EV_DoPlat(line,downWaitUpStay,0);
  585.             line->special = 0;
  586.             break;
  587.         case 12: // Light Turn On - brightest near
  588.             EV_LightTurnOn(line,0);
  589.             line->special = 0;
  590.             break;
  591.         case 13: // Light Turn On 255
  592.             EV_LightTurnOn(line,255);
  593.             line->special = 0;
  594.             break;
  595.         case 16: // Close Door 30
  596.             EV_DoDoor(line,close30ThenOpen,VDOORSPEED);
  597.             line->special = 0;
  598.             break;
  599.         case 17: // Start Light Strobing
  600.             EV_StartLightStrobing(line);
  601.             line->special = 0;
  602.             break;
  603.         case 19: // Lower Floor
  604.             EV_DoFloor(line,lowerFloor);
  605.             line->special = 0;
  606.             break;
  607.         case 22: // Raise floor to nearest height and change texture
  608.             EV_DoPlat(line,raiseToNearestAndChange,0);
  609.             line->special = 0;
  610.             break;
  611.         case 25: // Ceiling Crush and Raise
  612.             EV_DoCeiling(line,crushAndRaise);
  613.             line->special = 0;
  614.             break;
  615.         case 30:        // Raise floor to shortest texture height
  616.                         // on either side of lines
  617.             EV_DoFloor(line,raiseToTexture);
  618.             line->special = 0;
  619.             break;
  620.         case 35: // Lights Very Dark
  621.             EV_LightTurnOn(line,35);
  622.             line->special = 0;
  623.             break;
  624.         case 36: // Lower Floor (TURBO)
  625.             EV_DoFloor(line,turboLower);
  626.             line->special = 0;
  627.             break;
  628.         case 37: // LowerAndChange
  629.             EV_DoFloor(line,lowerAndChange);
  630.             line->special = 0;
  631.             break;
  632.         case 38: // Lower Floor To Lowest
  633.             EV_DoFloor( line, lowerFloorToLowest );
  634.             line->special = 0;
  635.             break;
  636.         case 39: // TELEPORT!
  637.             EV_Teleport( line, side, thing );
  638.             line->special = 0;
  639.             break;
  640.         case 40: // RaiseCeilingLowerFloor
  641.             EV_DoCeiling( line, raiseToHighest );
  642.             EV_DoFloor( line, lowerFloorToLowest );
  643.             line->special = 0;
  644.             break;
  645.         case 44: // Ceiling Crush
  646.             EV_DoCeiling( line, lowerAndCrush );
  647.             line->special = 0;
  648.             break;
  649.         case 52: // EXIT!
  650.             G_ExitLevel ();
  651.             line->special = 0;
  652.             break;
  653.         case 53: // Perpetual Platform Raise
  654.             EV_DoPlat(line,perpetualRaise,0);
  655.             line->special = 0;
  656.             break;
  657.         case 54: // Platform Stop
  658.             EV_StopPlat(line);
  659.             line->special = 0;
  660.             break;
  661.         case 56: // Raise Floor Crush
  662.             EV_DoFloor(line,raiseFloorCrush);
  663.             line->special = 0;
  664.             break;
  665.         case 57: // Ceiling Crush Stop
  666.             EV_CeilingCrushStop(line);
  667.             line->special = 0;
  668.             break;
  669.         case 58: // Raise Floor 24
  670.             EV_DoFloor(line,raiseFloor24);
  671.             line->special = 0;
  672.             break;
  673.         case 59: // Raise Floor 24 And Change
  674.             EV_DoFloor(line,raiseFloor24AndChange);
  675.             line->special = 0;
  676.             break;
  677.         case 104: // Turn lights off in sector(tag)
  678.             EV_TurnTagLightsOff(line);
  679.             line->special = 0;
  680.             break;
  681.         case 105: // Trigger_SecretExit
  682.             G_SecretExitLevel();
  683.             line->special = 0;
  684.             break;
  685.  
  686.     //====================================================
  687.     // RE-DOABLE TRIGGERS
  688.     //====================================================
  689.  
  690.         case 72:        // Ceiling Crush
  691.             EV_DoCeiling( line, lowerAndCrush );
  692.             break;
  693.         case 73:        // Ceiling Crush and Raise
  694.             EV_DoCeiling(line,crushAndRaise);
  695.             break;
  696.         case 74:        // Ceiling Crush Stop
  697.             EV_CeilingCrushStop(line);
  698.             break;
  699.         case 75:            // Close Door
  700.             EV_DoDoor(line,close,VDOORSPEED);
  701.             break;
  702.         case 76:        // Close Door 30
  703.             EV_DoDoor(line,close30ThenOpen,VDOORSPEED);
  704.             break;
  705.         case 77:            // Fast Ceiling Crush & Raise
  706.             EV_DoCeiling(line,fastCrushAndRaise);
  707.             break;
  708.         case 79:        // Lights Very Dark
  709.             EV_LightTurnOn(line,35);
  710.             break;
  711.         case 80:        // Light Turn On - brightest near
  712.             EV_LightTurnOn(line,0);
  713.             break;
  714.         case 81:        // Light Turn On 255
  715.             EV_LightTurnOn(line,255);
  716.             break;
  717.         case 82:        // Lower Floor To Lowest
  718.             EV_DoFloor( line, lowerFloorToLowest );
  719.             break;
  720.         case 83:        // Lower Floor
  721.             EV_DoFloor(line,lowerFloor);
  722.             break;
  723.         case 84:        // LowerAndChange
  724.             EV_DoFloor(line,lowerAndChange);
  725.             break;
  726.         case 86:            // Open Door
  727.             EV_DoDoor(line,open,VDOORSPEED);
  728.             break;
  729.         case 87:        // Perpetual Platform Raise
  730.             EV_DoPlat(line,perpetualRaise,0);
  731.             break;
  732.         case 88:        // PlatDownWaitUp
  733.             EV_DoPlat(line,downWaitUpStay,0);
  734.             break;
  735.         case 89:        // Platform Stop
  736.             EV_StopPlat(line);
  737.             break;
  738.         case 90:            // Raise Door
  739.             EV_DoDoor(line,normal,VDOORSPEED);
  740.             break;
  741.         case 100: // Retrigger_Raise_Door_Turbo
  742.             EV_DoDoor(line, normal, VDOORSPEED*3);
  743.             break;
  744.         case 91:            // Raise Floor
  745.             EV_DoFloor(line,raiseFloor);
  746.             break;
  747.         case 92:        // Raise Floor 24
  748.             EV_DoFloor(line,raiseFloor24);
  749.             break;
  750.         case 93:        // Raise Floor 24 And Change
  751.             EV_DoFloor(line,raiseFloor24AndChange);
  752.             break;
  753.         case 94:        // Raise Floor Crush
  754.             EV_DoFloor(line,raiseFloorCrush);
  755.             break;
  756.         case 95:        // Raise floor to nearest height and change texture
  757.             EV_DoPlat(line,raiseToNearestAndChange,0);
  758.             break;
  759.         case 96:        // Raise floor to shortest texture height
  760.                         // on either side of lines
  761.             EV_DoFloor(line,raiseToTexture);
  762.             break;
  763.         case 97:        // TELEPORT!
  764.             EV_Teleport( line, side, thing );
  765.             break;
  766.         case 98:        // Lower Floor (TURBO)
  767.             EV_DoFloor(line,turboLower);
  768.             break;
  769.     }
  770. }
  771.  
  772. //----------------------------------------------------------------------------
  773. //
  774. // PROC P_ShootSpecialLine
  775. //
  776. // Called when a thing shoots a special line.
  777. //
  778. //----------------------------------------------------------------------------
  779.  
  780. void P_ShootSpecialLine(mobj_t *thing, line_t *line)
  781. {
  782.     if(!thing->player)
  783.     { // Check if trigger allowed by non-player mobj
  784.         switch(line->special)
  785.         {
  786.             case 46: // Impact_OpenDoor
  787.                 break;
  788.             default:
  789.                 return;
  790.                 break;
  791.         }
  792.     }
  793.     switch(line->special)
  794.     {
  795.         case 24: // Impact_RaiseFloor
  796.             EV_DoFloor(line, raiseFloor);
  797.             P_ChangeSwitchTexture(line, 0);
  798.             break;
  799.         case 46: // Impact_OpenDoor
  800.             EV_DoDoor(line, open, VDOORSPEED);
  801.             P_ChangeSwitchTexture(line, 1);
  802.             break;
  803.         case 47: // Impact_RaiseFloorNear&Change
  804.             EV_DoPlat(line, raiseToNearestAndChange, 0);
  805.             P_ChangeSwitchTexture(line, 0);
  806.             break;
  807.     }
  808. }
  809.  
  810. //----------------------------------------------------------------------------
  811. //
  812. // PROC P_PlayerInSpecialSector
  813. //
  814. // Called every tic frame that the player origin is in a special sector.
  815. //
  816. //----------------------------------------------------------------------------
  817.  
  818. void P_PlayerInSpecialSector(player_t *player)
  819. {
  820.     sector_t *sector;
  821.     static int pushTab[5] = {
  822.         2048*5,
  823.         2048*10,
  824.         2048*25,
  825.         2048*30,
  826.         2048*35
  827.     };
  828.  
  829.     sector = player->mo->subsector->sector;
  830.     if(player->mo->z != sector->floorheight)
  831.     { // Player is not touching the floor
  832.         return;
  833.     }
  834.     switch(sector->special)
  835.     {
  836.         case 7: // Damage_Sludge
  837.             if(!(leveltime&31))
  838.             {
  839.                 P_DamageMobj(player->mo, NULL, NULL, 4);
  840.             }
  841.             break;
  842.         case 5: // Damage_LavaWimpy
  843.             if(!(leveltime&15))
  844.             {
  845.                 P_DamageMobj(player->mo, &LavaInflictor, NULL, 5);
  846.                 P_HitFloor(player->mo);
  847.             }
  848.             break;
  849.         case 16: // Damage_LavaHefty
  850.             if(!(leveltime&15))
  851.             {
  852.                 P_DamageMobj(player->mo, &LavaInflictor, NULL, 8);
  853.                 P_HitFloor(player->mo);
  854.             }
  855.             break;
  856.         case 4: // Scroll_EastLavaDamage
  857.             P_Thrust(player, 0, 2048*28);
  858.             if(!(leveltime&15))
  859.             {
  860.                 P_DamageMobj(player->mo, &LavaInflictor, NULL, 5);
  861.                 P_HitFloor(player->mo);
  862.             }
  863.             break;
  864.         case 9: // SecretArea
  865.             player->secretcount++;
  866.             sector->special = 0;
  867.             break;
  868.         case 11: // Exit_SuperDamage (DOOM E1M8 finale)
  869.             /*
  870.             player->cheats &= ~CF_GODMODE;
  871.             if(!(leveltime&0x1f))
  872.             {
  873.                 P_DamageMobj(player->mo, NULL, NULL, 20);
  874.             }
  875.             if(player->health <= 10)
  876.             {
  877.                 G_ExitLevel();
  878.             }
  879.             */
  880.             break;
  881.  
  882.         case 25: case 26: case 27: case 28: case 29: // Scroll_North
  883.             P_Thrust(player, ANG90, pushTab[sector->special-25]);
  884.             break;
  885.         case 20: case 21: case 22: case 23: case 24: // Scroll_East
  886.             P_Thrust(player, 0, pushTab[sector->special-20]);
  887.             break;
  888.         case 30: case 31: case 32: case 33: case 34: // Scroll_South
  889.             P_Thrust(player, ANG270, pushTab[sector->special-30]);
  890.             break;
  891.         case 35: case 36: case 37: case 38: case 39: // Scroll_West
  892.             P_Thrust(player, ANG180, pushTab[sector->special-35]);
  893.             break;
  894.  
  895.         case 40: case 41: case 42: case 43: case 44: case 45:
  896.         case 46: case 47: case 48: case 49: case 50: case 51:
  897.             // Wind specials are handled in (P_mobj):P_XYMovement
  898.             break;
  899.  
  900.         case 15: // Friction_Low
  901.             // Only used in (P_mobj):P_XYMovement and (P_user):P_Thrust
  902.             break;
  903.  
  904.         default:
  905.             I_Error("P_PlayerInSpecialSector: "
  906.                 "unknown special %i", sector->special);
  907.     }
  908. }
  909.  
  910. //----------------------------------------------------------------------------
  911. //
  912. // PROC P_UpdateSpecials
  913. //
  914. // Animate planes, scroll walls, etc.
  915. //
  916. //----------------------------------------------------------------------------
  917.  
  918. void P_UpdateSpecials(void)
  919. {
  920.     int i;
  921.     int pic;
  922.     anim_t *anim;
  923.     line_t *line;
  924.  
  925.     // Animate flats and textures
  926.     for(anim = anims; anim < lastanim; anim++)
  927.     {
  928.         for(i = anim->basepic; i < anim->basepic+anim->numpics; i++)
  929.         {
  930.             pic = anim->basepic+((leveltime/anim->speed+i)%anim->numpics);
  931.             if(anim->istexture)
  932.             {
  933.                 texturetranslation[i] = pic;
  934.             }
  935.             else
  936.             {
  937.                 flattranslation[i] = pic;
  938.             }
  939.         }
  940.     }
  941.     // Update scrolling texture offsets
  942.     for(i = 0; i < numlinespecials; i++)
  943.     {
  944.         line = linespeciallist[i];
  945.         switch(line->special)
  946.         {
  947.             case 48: // Effect_Scroll_Left
  948.                 sides[line->sidenum[0]].textureoffset += FRACUNIT;
  949.                 break;
  950.             case 99: // Effect_Scroll_Right
  951.                 sides[line->sidenum[0]].textureoffset -= FRACUNIT;
  952.                 break;
  953.         }
  954.     }
  955.     // Handle buttons
  956.     for(i = 0; i < MAXBUTTONS; i++)
  957.     {
  958.         if(buttonlist[i].btimer)
  959.         {
  960.             buttonlist[i].btimer--;
  961.             if(!buttonlist[i].btimer)
  962.             {
  963.                 switch(buttonlist[i].where)
  964.                 {
  965.                     case top:
  966.                         sides[buttonlist[i].line->sidenum[0]].toptexture =
  967.                             buttonlist[i].btexture;
  968.                         break;
  969.                     case middle:
  970.                         sides[buttonlist[i].line->sidenum[0]].midtexture =
  971.                             buttonlist[i].btexture;
  972.                         break;
  973.                     case bottom:
  974.                         sides[buttonlist[i].line->sidenum[0]].bottomtexture =
  975.                             buttonlist[i].btexture;
  976.                         break;
  977.                 }
  978.                 S_StartSound((mobj_t *)&buttonlist[i].soundorg, sfx_switch);
  979.                 memset(&buttonlist[i], 0, sizeof(button_t));
  980.             }
  981.         }
  982.     }    
  983. }
  984.  
  985. //============================================================
  986. //
  987. //    Special Stuff that can't be categorized
  988. //
  989. //============================================================
  990. int EV_DoDonut(line_t *line)
  991. {
  992.     sector_t    *s1;
  993.     sector_t    *s2;
  994.     sector_t    *s3;
  995.     int            secnum;
  996.     int            rtn;
  997.     int            i;
  998.     floormove_t        *floor;
  999.     
  1000.     secnum = -1;
  1001.     rtn = 0;
  1002.     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  1003.     {
  1004.         s1 = §ors[secnum];
  1005.         
  1006.         //    ALREADY MOVING?  IF SO, KEEP GOING...
  1007.         if (s1->specialdata)
  1008.             continue;
  1009.             
  1010.         rtn = 1;
  1011.         s2 = getNextSector(s1->lines[0],s1);
  1012.         for (i = 0;i < s2->linecount;i++)
  1013.         {
  1014.             if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
  1015.                 (s2->lines[i]->backsector == s1))
  1016.                 continue;
  1017.             s3 = s2->lines[i]->backsector;
  1018.  
  1019.             //
  1020.             //    Spawn rising slime
  1021.             //
  1022.             floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  1023.             P_AddThinker (&floor->thinker);
  1024.             s2->specialdata = floor;
  1025.             floor->thinker.function = T_MoveFloor;
  1026.             floor->type = donutRaise;
  1027.             floor->crush = false;
  1028.             floor->direction = 1;
  1029.             floor->sector = s2;
  1030.             floor->speed = FLOORSPEED / 2;
  1031.             floor->texture = s3->floorpic;
  1032.             floor->newspecial = 0;
  1033.             floor->floordestheight = s3->floorheight;
  1034.             
  1035.             //
  1036.             //    Spawn lowering donut-hole
  1037.             //
  1038.             floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  1039.             P_AddThinker (&floor->thinker);
  1040.             s1->specialdata = floor;
  1041.             floor->thinker.function = T_MoveFloor;
  1042.             floor->type = lowerFloor;
  1043.             floor->crush = false;
  1044.             floor->direction = -1;
  1045.             floor->sector = s1;
  1046.             floor->speed = FLOORSPEED / 2;
  1047.             floor->floordestheight = s3->floorheight;
  1048.             break;
  1049.         }
  1050.     }
  1051.     return rtn;
  1052. }
  1053.  
  1054. /*
  1055. ==============================================================================
  1056.  
  1057.                             SPECIAL SPAWNING
  1058.  
  1059. ==============================================================================
  1060. */
  1061. /*
  1062. ================================================================================
  1063. = P_SpawnSpecials
  1064. =
  1065. = After the map has been loaded, scan for specials that
  1066. = spawn thinkers
  1067. =
  1068. ===============================================================================
  1069. */
  1070.  
  1071. short    numlinespecials;
  1072. line_t    *linespeciallist[MAXLINEANIMS];
  1073.  
  1074. void P_SpawnSpecials (void)
  1075. {
  1076.     sector_t    *sector;
  1077.     int        i;
  1078.     int        episode;
  1079.  
  1080.     episode = 1;
  1081.     if (W_CheckNumForName("texture2") >= 0)
  1082.         episode = 2;
  1083.         
  1084.     //
  1085.     //    Init special SECTORs
  1086.     //
  1087.     sector = sectors;
  1088.     for (i=0 ; i<numsectors ; i++, sector++)
  1089.     {
  1090.         if (!sector->special)
  1091.             continue;
  1092.         switch (sector->special)
  1093.         {
  1094.             case 1:        // FLICKERING LIGHTS
  1095.                 P_SpawnLightFlash (sector);
  1096.                 break;
  1097.             case 2:        // STROBE FAST
  1098.                 P_SpawnStrobeFlash(sector,FASTDARK,0);
  1099.                 break;
  1100.             case 3:        // STROBE SLOW
  1101.                 P_SpawnStrobeFlash(sector,SLOWDARK,0);
  1102.                 break;
  1103.             case 4:        // STROBE FAST/DEATH SLIME
  1104.                 P_SpawnStrobeFlash(sector,FASTDARK,0);
  1105.                 sector->special = 4;
  1106.                 break;
  1107.             case 8:        // GLOWING LIGHT
  1108.                 P_SpawnGlowingLight(sector);
  1109.                 break;
  1110.             case 9:        // SECRET SECTOR
  1111.                 totalsecret++;
  1112.                 break;
  1113.             case 10:    // DOOR CLOSE IN 30 SECONDS
  1114.                 P_SpawnDoorCloseIn30 (sector);
  1115.                 break;
  1116.             case 12:    // SYNC STROBE SLOW
  1117.                 P_SpawnStrobeFlash (sector, SLOWDARK, 1);
  1118.                 break;
  1119.             case 13:    // SYNC STROBE FAST
  1120.                 P_SpawnStrobeFlash (sector, FASTDARK, 1);
  1121.                 break;
  1122.             case 14:    // DOOR RAISE IN 5 MINUTES
  1123.                 P_SpawnDoorRaiseIn5Mins (sector, i);
  1124.                 break;
  1125.         }
  1126.     }
  1127.         
  1128.     
  1129.     //
  1130.     //    Init line EFFECTs
  1131.     //
  1132.     numlinespecials = 0;
  1133.     for (i = 0;i < numlines; i++)
  1134.         switch(lines[i].special)
  1135.         {
  1136.             case 48: // Effect_Scroll_Left
  1137.             case 99: // Effect_Scroll_Right
  1138.                 linespeciallist[numlinespecials] = &lines[i];
  1139.                 numlinespecials++;
  1140.                 break;
  1141.         }
  1142.         
  1143.     //
  1144.     //    Init other misc stuff
  1145.     //
  1146.     for (i = 0;i < MAXCEILINGS;i++)
  1147.         activeceilings[i] = NULL;
  1148.     for (i = 0;i < MAXPLATS;i++)
  1149.         activeplats[i] = NULL;
  1150.     for (i = 0;i < MAXBUTTONS;i++)
  1151.         memset(&buttonlist[i],0,sizeof(button_t));
  1152. }
  1153.  
  1154. //----------------------------------------------------------------------------
  1155. //
  1156. // PROC P_InitAmbientSound
  1157. //
  1158. //----------------------------------------------------------------------------
  1159.  
  1160. void P_InitAmbientSound(void)
  1161. {
  1162.     AmbSfxCount = 0;
  1163.     AmbSfxVolume = 0;
  1164.     AmbSfxTics = 10*TICSPERSEC;
  1165.     AmbSfxPtr = AmbSndSeqInit;
  1166. }
  1167.  
  1168. //----------------------------------------------------------------------------
  1169. //
  1170. // PROC P_AddAmbientSfx
  1171. //
  1172. // Called by (P_mobj):P_SpawnMapThing during (P_setup):P_SetupLevel.
  1173. //
  1174. //----------------------------------------------------------------------------
  1175.  
  1176. void P_AddAmbientSfx(int sequence)
  1177. {
  1178.     if(AmbSfxCount == MAX_AMBIENT_SFX)
  1179.     {
  1180.         I_Error("Too many ambient sound sequences");
  1181.     }
  1182.     LevelAmbientSfx[AmbSfxCount++] = AmbientSfx[sequence];
  1183. }
  1184.  
  1185. //----------------------------------------------------------------------------
  1186. //
  1187. // PROC P_AmbientSound
  1188. //
  1189. // Called every tic by (P_tick):P_Ticker.
  1190. //
  1191. //----------------------------------------------------------------------------
  1192.  
  1193. void P_AmbientSound(void)
  1194. {
  1195.     afxcmd_t cmd;
  1196.     int sound;
  1197.     boolean done;
  1198.  
  1199.     if(!AmbSfxCount)
  1200.     { // No ambient sound sequences on current level
  1201.         return;
  1202.     }
  1203.     if(--AmbSfxTics)
  1204.     {
  1205.         return;
  1206.     }
  1207.     done = false;
  1208.     do
  1209.     {
  1210.         cmd = *AmbSfxPtr++;
  1211.         switch(cmd)
  1212.         {
  1213.             case afxcmd_play:
  1214.                 AmbSfxVolume = P_Random()>>2;
  1215.                 S_StartSoundAtVolume(NULL, *AmbSfxPtr++, AmbSfxVolume);
  1216.                 break;
  1217.             case afxcmd_playabsvol:
  1218.                 sound = *AmbSfxPtr++;
  1219.                 AmbSfxVolume = *AmbSfxPtr++;
  1220.                 S_StartSoundAtVolume(NULL, sound, AmbSfxVolume);
  1221.                 break;
  1222.             case afxcmd_playrelvol:
  1223.                 sound = *AmbSfxPtr++;
  1224.                 AmbSfxVolume += *AmbSfxPtr++;
  1225.                 if(AmbSfxVolume < 0)
  1226.                 {
  1227.                     AmbSfxVolume = 0;
  1228.                 }
  1229.                 else if(AmbSfxVolume > 127)
  1230.                 {
  1231.                     AmbSfxVolume = 127;
  1232.                 }            
  1233.                 S_StartSoundAtVolume(NULL, sound, AmbSfxVolume);
  1234.                 break;
  1235.             case afxcmd_delay:
  1236.                 AmbSfxTics = *AmbSfxPtr++;
  1237.                 done = true;
  1238.                 break;
  1239.             case afxcmd_delayrand:
  1240.                 AmbSfxTics = P_Random()&(*AmbSfxPtr++);
  1241.                 done = true;
  1242.                 break;
  1243.             case afxcmd_end:
  1244.                 AmbSfxTics = 6*TICSPERSEC+P_Random();
  1245.                 AmbSfxPtr = LevelAmbientSfx[P_Random()%AmbSfxCount];
  1246.                 done = true;
  1247.                 break;
  1248.             default:
  1249.                 I_Error("P_AmbientSound: Unknown afxcmd %d", cmd);
  1250.                 break;
  1251.         }
  1252.     } while(done == false);
  1253. }
  1254.